#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

/************** 拉链法 ****************/
/*
const int N = 1e5 + 3;  // N最好取质数，而且要距离2^n尽可能远
int h[N], e[N], ne[N], idx;
const int mod = 1e5;

// C++修正负数取模: n % k: (n % k + k) % k
void insert(int x)
{
    // x可能为负数
    int pos = (x % N + N) % N;
    e[idx] = x, ne[idx] = h[pos], h[pos] = idx++;
}
bool find(int x)
{
    int pos = (x % N + N) % N;
    for (int i = h[pos]; i != -1; i = ne[i])
        if (e[i] == x)
            return true;
    return false;
}
int main()
{
    memset(h, -1, sizeof h);
    int n;
    scanf("%d", &n);
    int x;
    char op;
    while (n--)
    {
        scanf(" %c %d", &op, &x);
        if (op == 'I')
        {
            insert(x);
        }
        else
        {
            if (find(x))
                puts("Yes");
            else
                puts("No");
        }
    }
    return 0;
}*/

/*********** 开放寻址法（比拉链法效率低一点） ************/
/*
const int N = 2e5 + 3; //一般开两倍
int h[N];
int find(int x)
{
    int k = (x % N + N) % N;
    // 取模操作是算术操作中最慢的, 所以考虑到用if
    while (h[k] != 0x3f3f3f3f && h[k] != x)
    {
        ++k;
        if(k == N) k = 0;
        //k = (k + 1) % N; //不要这样写
    }
    return k;
}
int main()
{
    memset(h, 0x3f, sizeof h);
    int n;
    scanf("%d", &n);
    int x;
    char op;
    while (n--)
    {
        scanf(" %c %d", &op, &x);
        int i = find(x);
        if (op == 'I')
        {
            h[i] = x;
        }
        else
        {
            if (h[i] == x)
                puts("Yes");
            else
                puts("No");
        }
    }
    return 0;
}*/

#if 0
/***************** 字符串哈希 ****************/
// 不能把字符映射成0。经验：P取131或13331时，Q取2^64, 99.99%不会冲突
// hash[L, R] = hash[R] - hash[L-1]*p^len  (len = R - L + 1)
// h数组可以用unsigned long long, 这样就不用取模了

typedef unsigned long long ull;
const int N = 1e5 + 10;
char s[N];
ull h[N];
const ull p = 131;

// //快速幂虽然已经很快了，但可以预处理出来p^1, p^2, p^3 ...
// ull pow(ull a, int len)
// {
//     if(len == 0) return 1;
//     ull t = pow(a, len / 2);
//     if(len % 2)
//         return t * t * a;
//     else
//         return t * t;
// }

ull ps[N]; // ps[i] 表示 p^i
ull get(int l, int r)
{
    return h[r] - h[l - 1] * ps[r - l + 1];
}
int main()
{
    ps[0] = 1; // p^0 = 1
    int n, m;
    scanf("%d %d %s", &n, &m, s + 1);
    for (int i = 1; i <= n; ++i)
    {
        h[i] = h[i - 1] * p + s[i];
        ps[i] = ps[i - 1] * p;
    }
    int l1, r1, l2, r2;
    while (m--)
    {
        scanf("%d %d %d %d", &l1, &r1, &l2, &r2);
        if (get(l1, r1) == get(l2, r2))
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}

/*课后：
kmp循环节

*/

/***************** ST表 *******************/
// 查询区间性质的数据结构，例如最大值，最小值，gcd等. 基于倍增思想
const int N = 5e5 + 10;
int st[N][20], lg2[N]; 
// st[i][j] 表示从i开始，长度为2^j的区间。st[i][j] = max(st[i][j - 1], st[i + 2^(j-1)][j - 1]);
// 查询[l, r]区间：2^k <= r-l+1, k = lg2(r-l+1), max(st[l][k], st[r - 2^k + 1][k])
int n, q, a[N];
// lg2[i] = lg2[i/2] + 1; ?? 证明
int main()
{
    scanf("%d%d", &n, &q);
    for(int i = 1; i <= n; ++i) 
    {
        scanf("%d", &a[i]);
        st[i][0] = a[i];
    }
    lg2[1] = 0;
    for(int i = 2; i <= n; ++i)
        lg2[i] = lg2[i >> 1] + 1;
    for(int j = 1; j < 20; ++j)
    {
        // 右端点为 i + (1 << j) - 1
        for(int i = 1; i + (1 << j) - 1 <= n; ++i)
        {
            st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
        }
    }
    while(q--)
    {
        int l, r, ans;
        scanf("%d%d", &l, &r);
        int k = lg2[r - l + 1];
        ans = max(st[l][k], st[r - (1 << k) + 1][k]);
        printf("%d\n", ans);
    }
    return 0;
}

// 3002 GCD不小于K的子数组

/***************** 树状数组 ***************/
// 关键：
// 1、t[i]长度: lowbit(i), 
// 2、t[i]父节点下标: i + lowbit(i)
/*
预处理t[i]:
    t[i] = sum[i] - sum[i - lowbit(i)];

单点修改：i位置元素上加上k
    for(; i <= n; i += lowbit(i))
        t[i] += k;

查询 i 位置前缀和：
    for(; i; i -= lowbit(i))
        ret += t[i];
    return ret;
*/

//************** 洛谷 P3374
// // 单点修改，区间查询
// const int N = 5e5 + 10;
// int a[N], t[N], n, m;

// inline int lowbit(int x)
// {
//     return x & -x;
// }

// void add(int i, int k)
// {
//     for(; i <= n; i += lowbit(i))
//         t[i] += k;
// }
// int ask(int i)
// {
//     int ret = 0;
//     for(; i; i -= lowbit(i))
//         ret += t[i];
//     return ret;
// }

// int main()
// {
//     scanf("%d%d", &n, &m);
//     for(int i = 1; i <= n; ++i)
//     {
//         scanf("%d", &a[i]);
//         a[i] += a[i - 1];
//         t[i] = a[i] - a[i - lowbit(i)];
//     }
//     int op, x, k, l, r;
//     while(m--)
//     {
//         scanf("%d", &op);
//         if(op == 1)
//         {
//             scanf("%d%d", &x, &k);
//             add(x, k);
//         }
//         else{
//             scanf("%d%d", &l, &r);
//             printf("%d\n", ask(r) - ask(l - 1));
//         }
//     }
//     return 0;
// }

//**************** 洛谷 P3368
// 区间修改，单点查询。直接差分
const int N = 500000 + 10;
int f[N], a[N], t[N], n, m;
// a[i] = f[1] + f[2] + ... + f[i]
// f[i] = a[i] - a[i-1]
// 
inline int lowbit(int x)
{
    return x & -x;
}

void add(int i, int k)
{
    for(; i <= n; i += lowbit(i))
        t[i] += k;
}
int ask(int i)
{
    int ret = 0;
    for(; i; i -= lowbit(i))
        ret += t[i];
    return ret;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i]);
        f[i] = a[i] - a[i - 1];
        t[i] = a[i] - a[i - lowbit(i)];
    }
    int op, l, r, x, k;
    while(m--)
    {
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d%d%d", &l, &r, &k);
            add(l, k), add(r + 1, -k);
        }
        else{
            scanf("%d", &x);
            printf("%d\n", ask(x));
        }
    }
    return 0;
}

//**  一个简单的整数问题2 https://www.acwing.com/problem/content/244/ 
// 树状数组-区间修改、区间查询
/*
区间修改：转换为差分
区间查询: sum(a[l ~ r]), 转化为sum(a[r]) - sum(a[l-1]). 即只需求出a[x]的前缀和
a1 = b1
a2 = b1 + b2
a3 = b1 + b2 + b3
.
.
ax = b1 + b2 + b3 + ... + bx

```个人思路，尚未想出
sum(a[x])   = x*b1 +    (x-1)*b2 + (x-2)*b3 + ... + bx
sum(a[x+1]) = (x+1)*b1 + x*b2 +    (x-1)*b3 + ... + 2*bx + b(x+1)
sum(a[x+1]) = sum(a[x]) + b1+b2+...+b(x+1)
            = sum(a[x]) + sum(b[x]);
我们要把sum(a[i]) 变为 sum(f(b[i])) 的形式，这样修改 a[l~r], 就要单点修改b[i]
```

有点涉及数学跟思维，我们想将sum(a[x]) 变为sum(f[x])
将上三角补齐：
     b1 + b2 + ...      + bx
a1 = b1 + ...           + bx
a2 = b1 + b2 + ...      + bx
a3 = b1 + b2 + b3 + ... + bx
.
.
ax = b1 + b2 + b3 + ... + bx

a1+...+ax = (b1 + b2 +...+ bx)*(x + 1) - (b1 + 2*b2 + 3*b3 + ... + x*bx)
令c[i] = i*b[i]
这样sum(a[i]) = sum(b[i])*(i+1) - sum(c[i]);
*/
const int N = 1e5 + 10;
int a[N], b[N], n, m;
ll t1[N], t2[N];

void add(ll t[], int i, ll k)
{
    for(; i <= n; i += i & -i)
        t[i] += k;
}

ll ask(ll t[], int i)
{
    ll ret = 0;
    for(; i; i -= i & -i)
        ret += t[i];
    return ret;
}

ll sum(int i)
{
    return ask(t1, i) * (i+1) - ask(t2, i);
}

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i]);
        b[i] = a[i] - a[i - 1];
        add(t1, i, b[i]);
        add(t2, i, (ll)i * b[i]); //相乘可能会爆int
    }
    char op;
    ll l, r, d; // 这里不会爆int，用int也能过
    while(m--)
    {
        scanf(" %c%lld%lld", &op, &l, &r);
        if(op == 'C')
        {
            scanf("%lld", &d);
            add(t1, l, d);
            add(t1, r + 1, -d);
            add(t2, l, l*d);
            add(t2, r + 1, -d*(r+1));
        }
        else
        {
            ll ans = sum(r) - sum(l - 1);
            printf("%lld\n", ans);
        }
    }
    return 0;
}

#endif
// *********** 谜一样的牛 https://www.acwing.com/problem/content/245/
// 问题核心：用树状数组找第k小的数。
// 用数组记录1~n每个数字能用几次，t[i] = 1表示i元素可以用1次，t[i] = 0表示i已用过，不能再用了
// 这样，找第k小的数，即为找sum(t[i]) == k的最小下标i，直接二分+树状数组。
const int N = 1e5 + 10;
int a[N], t[N], n;
int ans[N];

int lowbit(int x) { return x & -x; }

void add(int i, int k)
{
    for(; i <= n; i += lowbit(i))
        t[i] += k;
}

int sum(int i)
{
    int ret = 0;
    for(; i; i -= lowbit(i))
        ret += t[i];
    return ret;
}

int find(int k)
{
    int l = 1, r = n;
    while(l < r)
    {
        int mid = (l + r) >> 1;
        int t = sum(mid);
        if(t >= k) 
            r = mid;
        else 
            l = mid + 1;
    }
    return l;
}

int main()
{
    scanf("%d", &n);
    t[1] = 1;
    for(int i = 2; i <= n; ++i)
    {
        scanf("%d", &a[i]);
        t[i] = lowbit(i);
    }
    for(int i = n; i; --i)
    {
        int k = a[i] + 1;
        a[i] = find(k); // 找剩下的数中，第k小的数。即sum(i) == k
        add(a[i], -1);  // 用完后记得-1
    }
    for(int i = 1; i <= n; ++i)
        printf("%d ", a[i]);
    return 0;
}